'''
Knowtemarks
===========
A simple tool to manage your notes and bookmarks

@author: Markus Fuchs, 2012

Filters are designed to be chained in order to filter
knowtes with specific properties. They have an attribute
__skey which is used to give a total order of all SearchFilter
classes. A list of filters named "filters" should be sorted 
like this:
    sorted(filters, key=lambda s: s._sortkey)
'''

class SearchFilter(object):
    """
    The "interface" for all search filters.
    It is basically a filter which always returns
    all items, so does nothing.
    All other filter inheriting should overwrite all
    its methods
    
    filterAll() considers all items in the database
                and returns those matching the filter
                properties
    filter(items) considers only the list of items and
                  and returns a sub set of them that
                  matches the filter properties
    
    The description method is used in the view
    """
    def __init__(self, kDao = None):
        self._sortkey = 0
        self.kDao = kDao
    
    def filterAll(self):
        return self.kDao.getKnowtes()
    
    def filter(self, items):
        return items
    
    def description(self):
        return "All Items"
    
    def __skey(self):
        return type(self).__sortkey
    
    def __eq__(self,other):
        return type(self) == type(other)
    
    def __hash__(self):
        return 11234

    
class SearchStringFilter(SearchFilter):
    """
    Returns items which contain the given string in their title
    or info or they have a tag which exactly matches the string
    """
    def __init__(self, searchString, kDao=None):
        self._sortkey = 30
        self.kDao = kDao
        self.searchString = searchString.lower()
    
    def filterAll(self):
        return self.filter(self.kDao.getKnowtes())
    
    def filter(self, items):
        results = TagFilter(self.searchString).filter(items)
        for i in items:
            if i.title.lower().find(self.searchString) != -1 \
                or i.info.lower().find(self.searchString) != -1:
                results.append(i)
        return results
    def description(self):
        return "<i class=\"icon-search\"></i>&nbsp;" + self.searchString
    
    def __eq__(self,other):
        return type(self) == type(other) and self.searchString == other.searchString
    
    def __hash__(self):
        return self.searchString.__hash__()
    
class TagFilter(SearchFilter):
    """
    returns only items which have a tag named like the tag
    specified in this filter
    """
    def __init__(self, tag, kDao=None):
        self._sortkey = 20
        self.kDao = kDao
        self.tagname = tag
        
    def filterAll(self):
        return self.filter(self.kDao.getKnowtes()) # TODO performance
    
    def filter(self, items):
        results = []
        for i in items:
            if i.taglist().count(self.tagname) > 0:
                results.append(i)
        return results
    
    def description(self):
        return "<i class=\"icon-tags\"></i>&nbsp;" + self.tagname
    
    def __eq__(self,other):
        return type(self) == type(other) and self.tagname == other.tagname
    
    def __hash__(self):
        return self.tagname.__hash__() ^ 1 

   
class TypeFilter(SearchFilter):
    """
    return only items of the given type. This can be
    "note" or "bookmark"
    """
    def __init__(self, tpe, kDao=None):
        self._sortkey = 10
        self.kDao = kDao
        self.type = tpe
    
    def filterAll(self):
        return self.filter(self.kDao.getKnowtes()) # TODO performance
    
    def filter(self, items):
        results = []
        for i in items:
            if i.getType() == self.type:
                results.append(i)
        return results
    
    def description(self):
        if(self.type == "bookmark"):
            return "Bookmarks"
        else:
            return "Notes"
        
    def __eq__(self,other):
        return type(self) == type(other) and self.type == other.type
    
    def __hash__(self):
        return self.type.__hash__() ^ 2
     
